﻿
def my_abs1(x):
	if x > 0:
		return x
	else:
		return -x
	
def my_abs2(x):
	if not isinstance(x,(int,float)):
		raise TypeError('bad operand type')
	if x > 0:
		return x
	else:
		return -x
	
def nop():
	pass
	
# Python函数返回值其实还是一个值，看上去是两个值，其实一个tuple
def move(x,y,d):
	nx=x+d*0.5
	ny=y+d*0.5
	return nx,ny

def power(x,n=2):
	s=1
	while n>0:
		n=n-1
		s=s*x
	return s

# 必选参数在前，默认参数在后，否则Python的解释器会报错
# 当函数有多个参数时，把变化大的参数放前面，变化小的参数放后面。变化小的参数就可以作为默认参数。
def enroll(name,gender,age=6,city='Beijing'):
	print 'name:',name
	print 'gender:',gender
	print 'age:',age
	print 'city:',city

#Python函数在定义的时候，默认参数L的值就被计算出来了，即[]，因为默认参数L也是一个变量，它指向对象[]，
#每次调用该函数，如果改变了L的内容，则下次调用时，默认参数的内容就变了，不再是函数定义时的[]了。
def add_end_1(L=[]):
	L.append('END')
	return L
	
def add_end_2(L=None):
	if L is None:
		L=[]
	L.append("END")
	return L
	
def calc1(numbers):
	sum=0
	for n in numbers:
		sum=sum+n*n
	return sum

# 在Python函数中，还可以定义可变参数。顾名思义，可变参数就是传入的参数个数是可变的，可以是1个、2个到任意个，还可以是0个
# 定义可变参数和定义list或tuple参数相比，仅仅在参数前面加了一个*号。在函数内部，参数numbers接收到的是一个tuple，
# 因此，函数代码完全不变。但是，调用该函数时，可以传入任意个参数，包括0个参数
def calc2(*numbers):
	sum=0
	for n in numbers:
		sum=sum+n*n
	return sum

# 可变参数允许你传入0个或任意个参数，这些可变参数在函数调用时自动组装为一个tuple。
# 而关键字参数允许你传入0个或任意个含参数名的参数，这些关键字参数在函数内部自动组装为一个dict
def person(name,age,**kw):
	print "name =",name,"  age =",age,"  other",kw

# 在Python中定义函数，可以用必选参数、默认参数、可变参数和关键字参数，这4种参数都可以一起使用，或者只用其中某些，
# 但是请注意，参数定义的顺序必须是：必选参数、默认参数、可变参数和关键字参数。
def func(a,b,c=0,*args,**kw):
	print 'a =',a,'  b =',b,'  c =',c,'  args =',args,'  kw =',kw

# 尾递归是指，在函数返回的时候，调用自身本身，并且，return语句不能包含表达式。
# 这样，编译器或者解释器就可以把尾递归做优化，使递归本身无论调用多少次，都只占用一个栈帧，不会出现栈溢出的情况。
def fact1(n):
	if n==1:
		return 1
	return n*fact1(n-1)

def fact(n):
	return fact_iter(n,1)

def fact_iter(num,product):
	if num==1:
		return product
	return fact_iter(num-1,num*product)

print "------------------------------------------------------------------------------------------------"

print "my_abs1(-23) =",my_abs1(-23)
print "my_abs1('A') =",my_abs1('A')

print "my_abs2(-23) =",my_abs2(-23)
#print "my_abs2('A') =",my_abs2('A') #error

x,y=move(100,100,60)
print "x,y=move(100,100,60) x,y =",x,y
r=move(100,100,60)
print "move(100,100,60) =",r

print "nop() =",nop()

print "power(3) =",power(3)
print "power(3,4) =",power(3,4)

enroll('Sarah','F')
enroll('Bob','M',7)
enroll('Adam','M',city='Tianjin')

print "add_end_1([1,2,3])",add_end_1([1,2,3])
print "add_end_1()",add_end_1()
print "add_end_1()",add_end_1()
print "add_end_1()",add_end_1()

print "add_end_2([1,2,3])",add_end_2([1,2,3])
print "add_end_2()",add_end_2()
print "add_end_2()",add_end_2()
print "add_end_2()",add_end_2()

print "calc1([1,2,3]) =",calc1([1,2,3])
print "calc1([1,2,3,4]) =",calc1([1,2,3,4])
print "calc2() =",calc2()
print "calc2(1,2,3) =",calc2(1,2,3)
print "calc2(1,2,3,4) =",calc2(1,2,3,4)

nums=[1,2,3]
print "nums =",nums
print "calc1(nums) =",calc1(nums)
print "calc1(nums[0],nums[1],nums[2]) =",calc2(nums[0],nums[1],nums[2])
print "calc2(*nums) =",calc2(*nums)

print "person('Michael',40) =",person("Michael",40)
print "person('Bob',23,city='Beijing') =",person('Bob',23,city='Beijing')
print "person('Tracy',28,city='Beijing',job='Engineer') =",person('Tracy',28,city='Beijing',job='Engineer')

kw={'city':'Tianjin','job':'Engineer'}
print "kw =",kw
person('jack',24,city=kw['city'],job=kw['job'])
print "person('jack',24,city=kw['city'],job=kw['job']) =",person('jack',24,city=kw['city'],job=kw['job'])
print "person('Jack',24,**kw) =",person('Jack',24,**kw)

print "func(1,2) =",func(1,2)
print "func(1,2,c=3) =",func(1,2,c=3)
print "func(1,2,3,'a','b') =",func(1,2,3,'a','b')
print "func(1,2,3,'a','b',x=99)",func(1,2,3,'a','b',x=99)

args=(1,2,3,4)
kw={'x':99}
print "args =",args
print "kw =",kw
print "func(*args,**kw) =",func(*args,**kw)